home *** CD-ROM | disk | FTP | other *** search
- /* The executable class. Opens an executable file and reads info to
- get a pc to line mapping. This only works with files in a.out
- format. */
-
- #include <std.h>
- #include <iostream.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
- #include <stab.h>
- #include "execute.h"
-
- /* Some people seem to have include files where this is not defined */
- #ifndef MAP_FILE
- #define MAP_FILE 0
- #endif
-
- executable::executable(const char* file)
- {
- fd = open(file, O_RDONLY);
- if (fd == -1) {
- perror(file);
- exit(1);
- }
-
- stat flstat;
- if (stat(file, &flstat) == -1) {
- perror("Cannot stat executable");
- exit(1);
- }
- filesize = flstat.st_size;
- if (filesize < sizeof(exec)) {
- cerr << "File is too small to be an executable\n";
- exit(1);
- }
- _mtime = flstat.st_mtime;
-
- start = (unsigned int)mmap(0, filesize, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
- if (start == (unsigned int)-1) {
- perror("Cannot map executable");
- exit(1);
- }
- exec& header = *(exec*)start;
- if (N_BADMAG(header)) {
- cerr << "File doesn't seem to be an executable\n";
- exit(1);
- }
-
- if (!header.a_syms) {
- cerr << "No symbols in file!\n";
- exit(1);
- }
- cursym = (nlist*)(start + N_SYMOFF(header));
- strs = (char*)(start + N_STROFF(header));
- maxsym = (nlist*)((unsigned)cursym + header.a_syms);
-
- // Go to first line.
- shift();
- }
-
- executable::~executable(void)
- {
- munmap((caddr_t)start, filesize);
- close(fd);
- }
-
- int executable::shift(void)
- {
- while (++cursym < maxsym) {
- switch (cursym->n_type) {
- case N_SO:
- const char* nm = strs + (unsigned)cursym->n_un.n_name;
- if (nm[strlen(nm)-1] == '/') {
- cdir = nm;
- } else {
- cfile = nm;
- }
- break;
- case N_SOL:
- cfile = strs + (unsigned)cursym->n_un.n_name;
- break;
- case N_SLINE:
- cline = cursym->n_desc;
- clow = cursym->n_value;
- /* Look for next symbol to get high pc */
- nlist* nextsym = cursym;
- do {
- if (++nextsym == maxsym)
- return 0;
- } while (nextsym->n_type != N_SLINE);
- chigh = nextsym->n_value;
- return 1;
- }
- }
-
- return 0; // No more symbols.
- }
-